.\" Copyright (C) 1994, 1995, Daniel Quinlan <quinlan@yggdrasil.com>
.\" Copyright (C) 2002-2008, 2017, Michael Kerrisk <mtk.manpages@gmail.com>
.\" Copyright (C) 2023, Alejandro Colomar <alx@kernel.org>
.\"
.\" SPDX-License-Identifier: GPL-3.0-or-later
.\"
.TH proc_pid_fd 5 2024-05-02 "Linux man-pages 6.9.1"
.SH NAME
/proc/pid/fd/ \- file descriptors
.SH DESCRIPTION
.TP
.IR /proc/ pid /fd/
This is a subdirectory containing one entry for each file which the
process has open, named by its file descriptor, and which is a
symbolic link to the actual file.
Thus, 0 is standard input, 1 standard output, 2 standard error, and so on.
.IP
For file descriptors for pipes and sockets,
the entries will be symbolic links whose content is the
file type with the inode.
A
.BR readlink (2)
call on this file returns a string in the format:
.IP
.in +4n
.EX
type:[inode]
.EE
.in
.IP
For example,
.I socket:[2248868]
will be a socket and its inode is 2248868.
For sockets, that inode can be used to find more information
in one of the files under
.IR /proc/net/ .
.IP
For file descriptors that have no corresponding inode
(e.g., file descriptors produced by
.BR bpf (2),
.BR epoll_create (2),
.BR eventfd (2),
.BR inotify_init (2),
.BR perf_event_open (2),
.BR signalfd (2),
.BR timerfd_create (2),
and
.BR userfaultfd (2)),
the entry will be a symbolic link with contents of the form
.IP
.in +4n
.EX
.RI anon_inode: file-type
.EE
.in
.IP
In many cases (but not all), the
.I file-type
is surrounded by square brackets.
.IP
For example, an epoll file descriptor will have a symbolic link
whose content is the string
.IR "anon_inode:[eventpoll]" .
.IP
.\"The following was still true as at kernel 2.6.13
In a multithreaded process, the contents of this directory
are not available if the main thread has already terminated
(typically by calling
.BR pthread_exit (3)).
.IP
Programs that take a filename as a command-line argument,
but don't take input from standard input if no argument is supplied,
and programs that write to a file named as a command-line argument,
but don't send their output to standard output
if no argument is supplied, can nevertheless be made to use
standard input or standard output by using
.IR /proc/ pid /fd
files as command-line arguments.
For example, assuming that
.I \-i
is the flag designating an input file and
.I \-o
is the flag designating an output file:
.IP
.in +4n
.EX
.RB "$" " foobar \-i /proc/self/fd/0 \-o /proc/self/fd/1 ..."
.EE
.in
.IP
and you have a working filter.
.\" The following is not true in my tests (MTK):
.\" Note that this will not work for
.\" programs that seek on their files, as the files in the fd directory
.\" are not seekable.
.IP
.I /proc/self/fd/N
is approximately the same as
.I /dev/fd/N
in some UNIX and UNIX-like systems.
Most Linux MAKEDEV scripts symbolically link
.I /dev/fd
to
.IR /proc/self/fd ,
in fact.
.IP
Most systems provide symbolic links
.IR /dev/stdin ,
.IR /dev/stdout ,
and
.IR /dev/stderr ,
which respectively link to the files
.IR 0 ,
.IR 1 ,
and
.I 2
in
.IR /proc/self/fd .
Thus the example command above could be written as:
.IP
.in +4n
.EX
.RB "$" " foobar \-i /dev/stdin \-o /dev/stdout ..."
.EE
.in
.IP
Permission to dereference or read
.RB ( readlink (2))
the symbolic links in this directory is governed by a ptrace access mode
.B PTRACE_MODE_READ_FSCREDS
check; see
.BR ptrace (2).
.IP
Note that for file descriptors referring to inodes
(pipes and sockets, see above),
those inodes still have permission bits and ownership information
distinct from those of the
.IR /proc/ pid /fd
entry,
and that the owner may differ from the user and group IDs of the process.
An unprivileged process may lack permissions to open them, as in this example:
.IP
.in +4n
.EX
.RB "$" " echo test | sudo \-u nobody cat"
test
.RB "$" " echo test | sudo \-u nobody cat /proc/self/fd/0"
cat: /proc/self/fd/0: Permission denied
.EE
.in
.IP
File descriptor 0 refers to the pipe created by the shell
and owned by that shell's user, which is not
.IR nobody ,
so
.B cat
does not have permission
to create a new file descriptor to read from that inode,
even though it can still read from its existing file descriptor 0.
.SH SEE ALSO
.BR proc (5)
